﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Diagnostics;
using System.Reflection;

namespace NFinal.AutoConfig
{
    public class Project
    {
        //dl引用实体类
        public class Assm
        {
            //是否是framework内部引用
            public bool IsFrameWork = false;
            //引入路径
            public Assm(string Include)
            {
                this.Include = Include;
                IsFrameWork = true;
            }
            //初始化函数
            public Assm(string Include, bool SpecificVersion, string HintPath)
            {
                this.Include = Include;
                this.SpecificVersion = SpecificVersion;
                this.HintPath = HintPath;
                IsFrameWork = false;
            }
            //获取相关的xml
            public XmlNode GetXMLNode(XmlDocument doc, string nameSpace)
            {
                XmlNode nodeReference = doc.CreateElement("Reference", nameSpace);
                XmlAttribute attrInclude = doc.CreateAttribute("Include");
                attrInclude.Value = this.Include;
                nodeReference.Attributes.Append(attrInclude);
                if (!IsFrameWork)
                {
                    XmlNode nodeSpecificVersion = doc.CreateElement("SpecificVersion", nameSpace);
                    nodeSpecificVersion.InnerText = this.SpecificVersion.ToString();
                    XmlNode nodeHintPath = doc.CreateElement("HintPath", nameSpace);
                    nodeHintPath.InnerText = this.HintPath;
                    nodeReference.AppendChild(nodeSpecificVersion);
                    nodeReference.AppendChild(nodeHintPath);
                }
                return nodeReference;
            }
            public string Include = string.Empty;
            public bool SpecificVersion = false;
            public string HintPath = string.Empty;
        }
        private string projectFile=null;
        private XmlNamespaceManager namespaceManager = null;
        private XmlDocument doc = null;
        private string root;
        //private bool hasChanged=false;
        private string nameSpace = null;
        public Project(string projectFile)
        {
            this.projectFile = projectFile;
            this.root= new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.FullName + "\\";
            //修改工程文件,加入dll引入
            doc = new System.Xml.XmlDocument();
            doc.Load(projectFile);
            nameSpace = doc.DocumentElement.Attributes["xmlns"].Value;
            namespaceManager = new XmlNamespaceManager(doc.NameTable);
            namespaceManager.AddNamespace("x", nameSpace);
        }
        public void Save()
        {
            doc.Save(projectFile);
        }
        //将相对根目录的路径转为绝对路径
        public string MapPath(string url)
        {
            return root + url.Trim('/').Replace('/', '\\');
        }
        public string MPath(string url)
        {
            return  url.Replace(root,"")+"\\";
        }
        public static void CopyLibrary(string root)
        {
            Assm AssmSQLite = new Assm("System.Data.SQLite, Version=1.0.96.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL",
        false, "NFinal/Resource/System.Data.SQLite.dll");
            Assm AssmMySQL = new Assm("MySql.Data, Version=5.1.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL",
                false, "NFinal/Resource/MySql.Data.dll");
            Assm AssmOracle = new Assm("Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=MSIL",
                false, "NFinal/Resource/Oracle.ManagedDataAccess.dll");
            System.Collections.Generic.List<Assm> AssmList = new System.Collections.Generic.List<Assm>();
            AssmList.Add(AssmSQLite);
            AssmList.Add(AssmMySQL);
            AssmList.Add(AssmOracle);

            //复制文件到执行目录下
            string dllFileName = null;
            string resourceName = null;
            for (int i = 0; i < AssmList.Count; i++)
            {
                if (!AssmList[i].IsFrameWork)
                {
                    dllFileName = root + "\\bin\\" + Path.GetFileName(AssmList[i].HintPath);
                    resourceName = root + "\\" + AssmList[i].HintPath.Replace('/', '\\');
                    if (!File.Exists(dllFileName))
                    {
                        File.Copy(resourceName, dllFileName);
                    }
                }
            }
            //引入32位64位通用dll文件
            if (!File.Exists(root + "\\bin\\x64\\SQLite.Interop.dll"))
            {
                File.Copy(root + "\\NFinal\\Resource\\x64\\SQLite.Interop.dll", GetFileName(root + "\\bin\\x64\\SQLite.Interop.dll"), true);
            }
            if (!File.Exists(root + "\\bin\\x86\\SQLite.Interop.dll"))
            {
                File.Copy(root + "\\NFinal\\Resource\\x86\\SQLite.Interop.dll", GetFileName(root + "\\bin\\x86\\SQLite.Interop.dll"), true);
            }
        }
        //添加DLL引用
        public void AddLibrary()
        {
            Assm AssmSQLite = new Assm("System.Data.SQLite",
                    false, "NFinal/Resource/System.Data.SQLite.dll");
            Assm AssmMySQL = new Assm("MySql.Data",
                false, "NFinal/Resource/MySql.Data.dll");
            Assm AssmOracle = new Assm("Oracle.ManagedDataAccess",
                false,"NFinal/Resource/Oracle.ManagedDataAccess.dll");
            Assm AssmNpgsql = new Assm("Npgsql",
                false, "NFinal/Resource/Npgsql.dll");
            Assm AssmNFinal4 = new Assm("NFinal4",
                false,"NFinal/Resource/NFinal4.dll");
            System.Collections.Generic.List<Assm> AssmList = new System.Collections.Generic.List<Assm>();
            AssmList.Add(AssmSQLite);
            AssmList.Add(AssmMySQL);
            AssmList.Add(AssmOracle);
            AssmList.Add(AssmNpgsql);
            AssmList.Add(AssmNFinal4);
            AssmList.Add(new Assm("Microsoft.CSharp"));
            AssmList.Add(new Assm("System"));
            AssmList.Add(new Assm("System.Data"));
            AssmList.Add(new Assm("System.Drawing"));
            AssmList.Add(new Assm("System.Web"));

            //复制文件到执行目录下
            string root = Path.GetDirectoryName(projectFile);
            string dllFileName = null;
            string resourceName = null;
            for (int i = 0; i < AssmList.Count; i++)
            {
                if (!AssmList[i].IsFrameWork)
                {
                    dllFileName = root + "\\bin\\" + Path.GetFileName(AssmList[i].HintPath); 
                    resourceName = root +"\\"+ AssmList[i].HintPath.Replace('/', '\\');
                    if (!File.Exists(dllFileName))
                    {
                        File.Copy(resourceName, dllFileName);
                    }
                }
            }
            XmlNode GroupReference = doc.DocumentElement.SelectSingleNode("x:ItemGroup/x:Reference[1]", namespaceManager).ParentNode;
            string xpath = null;
            for (int i = 0; i < AssmList.Count; i++)
            {
                xpath = string.Format("x:Reference[@Include='{0}']", AssmList[i].Include);
                XmlNode node = GroupReference.SelectSingleNode(xpath, namespaceManager);
                if (node == null)
                {
                    GroupReference.AppendChild(AssmList[i].GetXMLNode(doc, nameSpace));
                }
            }
            //去掉Newtonsoft引用
            //<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
            //< SpecificVersion > False </ SpecificVersion >
            //< HintPath > bin\Newtonsoft.Json.dll </ HintPath >
            //</ Reference >
            XmlNode newtonsoftNode = doc.DocumentElement.SelectSingleNode("x:ItemGroup/x:Reference[contains(@Include,'Newtonsoft.Json')]",namespaceManager);
            if (newtonsoftNode != null)
            {
                newtonsoftNode.ParentNode.RemoveChild(newtonsoftNode);
            }
            //引入32位64位通用dll文件
            if (!File.Exists(root + "\\bin\\x64\\SQLite.Interop.dll"))
            {
                File.Copy(root + "\\NFinal\\Resource\\x64\\SQLite.Interop.dll",GetFileName(root + "\\bin\\x64\\SQLite.Interop.dll"), true);
            }
            if (!File.Exists(root + "\\bin\\x86\\SQLite.Interop.dll"))
            {
                File.Copy(root + "\\NFinal\\Resource\\x86\\SQLite.Interop.dll",GetFileName(root + "\\bin\\x86\\SQLite.Interop.dll"), true);
            }
        }
        public static string GetFileName(string fileName)
        {
            string dir = Path.GetDirectoryName(fileName);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            return fileName;
        }
        public bool hasAdded(string fileName)
        {
            return true;
        }
        /// <summary>
        /// 添加文件夹
        /// </summary>
        /// <param name="folderName"></param>
        public void AddFolder(string folderName)
        {
            //<Folder Include="AA\Models\BLL" />
            string relativeFileName = folderName.Substring(root.Length);
            string folderInclude = string.Format("x:ItemGroup/x:Folder[@Include='{0}']", relativeFileName);
            XmlNode node = doc.DocumentElement.SelectSingleNode(folderInclude,namespaceManager);
            if (node == null)
            {
                XmlNode GroupInclude= doc.DocumentElement.SelectSingleNode("x:ItemGroup[2]", namespaceManager);
                XmlNode FolderNode = doc.CreateElement("Folder", nameSpace);
                XmlAttribute FolderNodeIncludeAttr = doc.CreateAttribute("Include");
                FolderNodeIncludeAttr.Value = relativeFileName;
                FolderNode.Attributes.Append(FolderNodeIncludeAttr);
                GroupInclude.AppendChild(FolderNode);
            }
        }
        /// <summary>
        /// 添加文件
        /// </summary>
        /// <param name="fileName"></param>
        public  void AddFile(string fileName)
        {
            XmlNode GroupInclude = doc.DocumentElement.SelectSingleNode("x:ItemGroup[2]", namespaceManager);
            string relativeFileName = fileName.Substring(root.Length);
            string shortFileName = Path.GetFileName(fileName);
            if (fileName.EndsWith(".cs"))
            {
                //截取Include值
                string compileInclude = string.Format("x:ItemGroup/x:Compile[@Include='{0}']", relativeFileName);
                XmlNode node = doc.DocumentElement.SelectSingleNode(compileInclude, namespaceManager);
                if (node == null)
                {
                    //<Compile Include="App\Handler1.ashx.cs">
                    //</Compile>
                    XmlNode CompileNode = doc.CreateElement("Compile", nameSpace);
                    XmlAttribute CompileNodeIncludeAttr = doc.CreateAttribute("Include");
                    CompileNodeIncludeAttr.Value = relativeFileName;
                    CompileNode.Attributes.Append(CompileNodeIncludeAttr);
                    //<Compile Include="App\Handler1.ashx.cs">
                    //< DependentUpon > Handler1.ashx </ DependentUpon >
                    //</ Compile >
                    if (fileName.EndsWith(".ashx.cs"))
                    {
                        XmlNode DependentUponNode = doc.CreateElement("DependentUpon", nameSpace);
                        DependentUponNode.InnerText =shortFileName.Substring(0, shortFileName.Length - 3);
                        CompileNode.AppendChild(DependentUponNode);
                    }
                    //<Compile Include="App\Views\Default\Common\Public\Success.aspx.cs">
                    //< DependentUpon > Success.aspx </ DependentUpon >
                    //< SubType > ASPXCodeBehind </ SubType >
                    //</ Compile >
                    else if (fileName.EndsWith(".aspx.cs"))
                    {
                        XmlNode DependentUponNode = doc.CreateElement("DependentUpon", nameSpace);
                        DependentUponNode.InnerText = shortFileName.Substring(0, shortFileName.Length - 3);
                        XmlNode SubTypeNode = doc.CreateElement("SubType", nameSpace);
                        SubTypeNode.InnerText = "ASPXCodeBehind";
                        CompileNode.AppendChild(DependentUponNode);
                        CompileNode.AppendChild(SubTypeNode);
                    }
                    //<Compile Include="App\Views\Default\Common\Public\Success.aspx.designer.cs">
                    //< DependentUpon > Success.aspx </ DependentUpon >
                    //</ Compile >
                    else if (fileName.EndsWith(".designer.cs"))
                    {
                        XmlNode DependentUponNode = doc.CreateElement("DependentUpon", nameSpace);
                        DependentUponNode.InnerText = shortFileName.Substring(0, shortFileName.Length - 12);
                        CompileNode.AppendChild(DependentUponNode);
                    }
                    //<Compile Include="App\Views\Default\Common\Public\Footer.ascx.designer.cs">
                    //< DependentUpon > Footer.ascx </ DependentUpon >
                    //</ Compile >
                    else if (fileName.EndsWith(".ascx.cs"))
                    {
                        XmlNode DependentUponNode = doc.CreateElement("DependentUpon", nameSpace);
                        DependentUponNode.InnerText = shortFileName.Substring(0, shortFileName.Length - 3);
                        XmlNode SubTypeNode = doc.CreateElement("SubType", nameSpace);
                        SubTypeNode.InnerText = "ASPXCodeBehind";
                        CompileNode.AppendChild(DependentUponNode);
                        CompileNode.AppendChild(SubTypeNode);
                    }
                    //<Compile Include="App\Models\Tips\Common\users.cs" />
                    else
                    {
                        XmlNode SubTypeNode = doc.CreateElement("SubType", nameSpace);
                        SubTypeNode.InnerText = "Code";
                        CompileNode.AppendChild(SubTypeNode);
                    }
                    GroupInclude.AppendChild(CompileNode);
                }
            }
            else if (fileName.EndsWith(".Debug.config") || fileName.EndsWith(".Release.config"))
            {
            }
            else
            {
                string fileInclude = string.Format("x:ItemGroup/x:Content[@Include='{0}']", relativeFileName);
                XmlNode node = doc.DocumentElement.SelectSingleNode(fileInclude, namespaceManager);
                if (node == null)
                {
                    XmlNode ContentNode = doc.CreateElement("Content", nameSpace);
                    XmlAttribute ContentNodeIncludeAttr = doc.CreateAttribute("Include");
                    ContentNodeIncludeAttr.Value = relativeFileName;
                    ContentNode.Attributes.Append(ContentNodeIncludeAttr);
                    GroupInclude.AppendChild(ContentNode);
                }
            }
        }
        /// <summary>
        /// 添加文件夹下所有文件
        /// </summary>
        /// <param name="folder"></param>
        public void AddFiles(string folder)
        {
            AddFolder(folder);
            string[] fileNames = Directory.GetFiles(folder);//查找指定目录下文件名
            foreach (string fileName in fileNames)
            {
                AddFile(fileName);
            }
            string[] folderNames = Directory.GetDirectories(folder);//查询指定路径下的子目录
            foreach (string folderName in folderNames)
            {
                AddFiles(folderName);
            }
        }
        /// <summary>
        /// 添加模块
        /// </summary>
        /// <param name="folder"></param>
        public void AddModule(string folder)
        {
            AddFiles(folder);
            AddFile(MapPath("IDE.html"));
            AddFile(MapPath("Router.cs"));
            AddFile(MapPath("Url.cs"));
            AddFile(MapPath("Url.js"));
            AddFile(MapPath("Web.config"));
        }
    }
}
